{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Final Machine Learning Pipeline\n",
    "\n",
    "The pipeline features\n",
    "\n",
    "- open source classes\n",
    "- in house package classes\n",
    "- only uses the selected features\n",
    "- we score new data"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Reproducibility: Setting the seed\n",
    "\n",
    "With the aim to ensure reproducibility between runs of the same notebook, but also between the research and production environment, for each step that includes some element of randomness, it is extremely important that we **set the seed**."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "# data manipulation and plotting\n",
    "import pandas as pd\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "# for saving the pipeline\n",
    "import joblib\n",
    "\n",
    "# from Scikit-learn\n",
    "from sklearn.linear_model import Lasso\n",
    "from sklearn.metrics import mean_squared_error, r2_score\n",
    "from sklearn.model_selection import train_test_split\n",
    "from sklearn.pipeline import Pipeline\n",
    "from sklearn.preprocessing import MinMaxScaler, Binarizer\n",
    "\n",
    "# from feature-engine\n",
    "from feature_engine.imputation import (\n",
    "    AddMissingIndicator,\n",
    "    MeanMedianImputer,\n",
    "    CategoricalImputer,\n",
    ")\n",
    "\n",
    "from feature_engine.encoding import (\n",
    "    RareLabelEncoder,\n",
    "    OrdinalEncoder,\n",
    ")\n",
    "\n",
    "from feature_engine.transformation import LogTransformer\n",
    "\n",
    "from feature_engine.selection import DropFeatures\n",
    "from feature_engine.wrappers import SklearnTransformerWrapper\n",
    "\n",
    "import preprocessors as pp"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(1460, 81)\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Id</th>\n",
       "      <th>MSSubClass</th>\n",
       "      <th>MSZoning</th>\n",
       "      <th>LotFrontage</th>\n",
       "      <th>LotArea</th>\n",
       "      <th>Street</th>\n",
       "      <th>Alley</th>\n",
       "      <th>LotShape</th>\n",
       "      <th>LandContour</th>\n",
       "      <th>Utilities</th>\n",
       "      <th>...</th>\n",
       "      <th>PoolArea</th>\n",
       "      <th>PoolQC</th>\n",
       "      <th>Fence</th>\n",
       "      <th>MiscFeature</th>\n",
       "      <th>MiscVal</th>\n",
       "      <th>MoSold</th>\n",
       "      <th>YrSold</th>\n",
       "      <th>SaleType</th>\n",
       "      <th>SaleCondition</th>\n",
       "      <th>SalePrice</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>1</td>\n",
       "      <td>60</td>\n",
       "      <td>RL</td>\n",
       "      <td>65.0</td>\n",
       "      <td>8450</td>\n",
       "      <td>Pave</td>\n",
       "      <td>NaN</td>\n",
       "      <td>Reg</td>\n",
       "      <td>Lvl</td>\n",
       "      <td>AllPub</td>\n",
       "      <td>...</td>\n",
       "      <td>0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0</td>\n",
       "      <td>2</td>\n",
       "      <td>2008</td>\n",
       "      <td>WD</td>\n",
       "      <td>Normal</td>\n",
       "      <td>208500</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>2</td>\n",
       "      <td>20</td>\n",
       "      <td>RL</td>\n",
       "      <td>80.0</td>\n",
       "      <td>9600</td>\n",
       "      <td>Pave</td>\n",
       "      <td>NaN</td>\n",
       "      <td>Reg</td>\n",
       "      <td>Lvl</td>\n",
       "      <td>AllPub</td>\n",
       "      <td>...</td>\n",
       "      <td>0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0</td>\n",
       "      <td>5</td>\n",
       "      <td>2007</td>\n",
       "      <td>WD</td>\n",
       "      <td>Normal</td>\n",
       "      <td>181500</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>3</td>\n",
       "      <td>60</td>\n",
       "      <td>RL</td>\n",
       "      <td>68.0</td>\n",
       "      <td>11250</td>\n",
       "      <td>Pave</td>\n",
       "      <td>NaN</td>\n",
       "      <td>IR1</td>\n",
       "      <td>Lvl</td>\n",
       "      <td>AllPub</td>\n",
       "      <td>...</td>\n",
       "      <td>0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0</td>\n",
       "      <td>9</td>\n",
       "      <td>2008</td>\n",
       "      <td>WD</td>\n",
       "      <td>Normal</td>\n",
       "      <td>223500</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>4</td>\n",
       "      <td>70</td>\n",
       "      <td>RL</td>\n",
       "      <td>60.0</td>\n",
       "      <td>9550</td>\n",
       "      <td>Pave</td>\n",
       "      <td>NaN</td>\n",
       "      <td>IR1</td>\n",
       "      <td>Lvl</td>\n",
       "      <td>AllPub</td>\n",
       "      <td>...</td>\n",
       "      <td>0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0</td>\n",
       "      <td>2</td>\n",
       "      <td>2006</td>\n",
       "      <td>WD</td>\n",
       "      <td>Abnorml</td>\n",
       "      <td>140000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>5</td>\n",
       "      <td>60</td>\n",
       "      <td>RL</td>\n",
       "      <td>84.0</td>\n",
       "      <td>14260</td>\n",
       "      <td>Pave</td>\n",
       "      <td>NaN</td>\n",
       "      <td>IR1</td>\n",
       "      <td>Lvl</td>\n",
       "      <td>AllPub</td>\n",
       "      <td>...</td>\n",
       "      <td>0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0</td>\n",
       "      <td>12</td>\n",
       "      <td>2008</td>\n",
       "      <td>WD</td>\n",
       "      <td>Normal</td>\n",
       "      <td>250000</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>5 rows × 81 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "   Id  MSSubClass MSZoning  LotFrontage  LotArea Street Alley LotShape  \\\n",
       "0   1          60       RL         65.0     8450   Pave   NaN      Reg   \n",
       "1   2          20       RL         80.0     9600   Pave   NaN      Reg   \n",
       "2   3          60       RL         68.0    11250   Pave   NaN      IR1   \n",
       "3   4          70       RL         60.0     9550   Pave   NaN      IR1   \n",
       "4   5          60       RL         84.0    14260   Pave   NaN      IR1   \n",
       "\n",
       "  LandContour Utilities  ... PoolArea PoolQC Fence MiscFeature MiscVal MoSold  \\\n",
       "0         Lvl    AllPub  ...        0    NaN   NaN         NaN       0      2   \n",
       "1         Lvl    AllPub  ...        0    NaN   NaN         NaN       0      5   \n",
       "2         Lvl    AllPub  ...        0    NaN   NaN         NaN       0      9   \n",
       "3         Lvl    AllPub  ...        0    NaN   NaN         NaN       0      2   \n",
       "4         Lvl    AllPub  ...        0    NaN   NaN         NaN       0     12   \n",
       "\n",
       "  YrSold  SaleType  SaleCondition  SalePrice  \n",
       "0   2008        WD         Normal     208500  \n",
       "1   2007        WD         Normal     181500  \n",
       "2   2008        WD         Normal     223500  \n",
       "3   2006        WD        Abnorml     140000  \n",
       "4   2008        WD         Normal     250000  \n",
       "\n",
       "[5 rows x 81 columns]"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# load dataset\n",
    "data = pd.read_csv('train.csv')\n",
    "\n",
    "# rows and columns of the data\n",
    "print(data.shape)\n",
    "\n",
    "# visualise the dataset\n",
    "data.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Cast MSSubClass as object\n",
    "\n",
    "data['MSSubClass'] = data['MSSubClass'].astype('O')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Separate dataset into train and test\n",
    "\n",
    "It is important to separate our data intro training and testing set. \n",
    "\n",
    "When we engineer features, some techniques learn parameters from data. It is important to learn these parameters only from the train set. This is to avoid over-fitting.\n",
    "\n",
    "Our feature engineering techniques will learn:\n",
    "\n",
    "- mean\n",
    "- mode\n",
    "- exponents for the yeo-johnson\n",
    "- category frequency\n",
    "- and category to number mappings\n",
    "\n",
    "from the train set.\n",
    "\n",
    "**Separating the data into train and test involves randomness, therefore, we need to set the seed.**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "((1314, 79), (146, 79))"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Let's separate into train and test set\n",
    "# Remember to set the seed (random_state for this sklearn function)\n",
    "\n",
    "X_train, X_test, y_train, y_test = train_test_split(\n",
    "    data.drop(['Id', 'SalePrice'], axis=1), # predictive variables\n",
    "    data['SalePrice'], # target\n",
    "    test_size=0.1, # portion of dataset to allocate to test set\n",
    "    random_state=0, # we are setting the seed here\n",
    ")\n",
    "\n",
    "X_train.shape, X_test.shape"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Target\n",
    "\n",
    "We apply the logarithm"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "y_train = np.log(y_train)\n",
    "y_test = np.log(y_test)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Configuration"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "# categorical variables with NA in train set\n",
    "CATEGORICAL_VARS_WITH_NA_FREQUENT = ['BsmtQual', 'BsmtExposure',\n",
    "                                     'BsmtFinType1', 'GarageFinish']\n",
    "\n",
    "\n",
    "CATEGORICAL_VARS_WITH_NA_MISSING = ['FireplaceQu']\n",
    "\n",
    "\n",
    "# numerical variables with NA in train set\n",
    "NUMERICAL_VARS_WITH_NA = ['LotFrontage']\n",
    "\n",
    "\n",
    "TEMPORAL_VARS = ['YearRemodAdd']\n",
    "REF_VAR = \"YrSold\"\n",
    "\n",
    "# this variable is to calculate the temporal variable,\n",
    "# can be dropped afterwards\n",
    "DROP_FEATURES = [\"YrSold\"]\n",
    "\n",
    "# variables to log transform\n",
    "NUMERICALS_LOG_VARS = [\"LotFrontage\", \"1stFlrSF\", \"GrLivArea\"]\n",
    "\n",
    "\n",
    "# variables to binarize\n",
    "BINARIZE_VARS = ['ScreenPorch']\n",
    "\n",
    "# variables to map\n",
    "QUAL_VARS = ['ExterQual', 'BsmtQual',\n",
    "             'HeatingQC', 'KitchenQual', 'FireplaceQu']\n",
    "\n",
    "EXPOSURE_VARS = ['BsmtExposure']\n",
    "\n",
    "FINISH_VARS = ['BsmtFinType1']\n",
    "\n",
    "GARAGE_VARS = ['GarageFinish']\n",
    "\n",
    "FENCE_VARS = ['Fence']\n",
    "\n",
    "\n",
    "# categorical variables to encode\n",
    "CATEGORICAL_VARS = ['MSSubClass',  'MSZoning',  'LotShape',  'LandContour',\n",
    "                    'LotConfig', 'Neighborhood', 'RoofStyle', 'Exterior1st',\n",
    "                    'Foundation', 'CentralAir', 'Functional', 'PavedDrive',\n",
    "                    'SaleCondition']\n",
    "\n",
    "\n",
    "# variable mappings\n",
    "QUAL_MAPPINGS = {'Po': 1, 'Fa': 2, 'TA': 3,\n",
    "                 'Gd': 4, 'Ex': 5, 'Missing': 0, 'NA': 0}\n",
    "\n",
    "EXPOSURE_MAPPINGS = {'No': 1, 'Mn': 2, 'Av': 3, 'Gd': 4}\n",
    "\n",
    "FINISH_MAPPINGS = {'Missing': 0, 'NA': 0, 'Unf': 1,\n",
    "                   'LwQ': 2, 'Rec': 3, 'BLQ': 4, 'ALQ': 5, 'GLQ': 6}\n",
    "\n",
    "GARAGE_MAPPINGS = {'Missing': 0, 'NA': 0, 'Unf': 1, 'RFn': 2, 'Fin': 3}\n",
    "\n",
    "\n",
    "# the selected variables\n",
    "FEATURES = [\n",
    "    'MSSubClass',\n",
    "    'MSZoning',\n",
    "    'LotFrontage',\n",
    "    'LotShape',\n",
    "    'LandContour',\n",
    "    'LotConfig',\n",
    "    'Neighborhood',\n",
    "    'OverallQual',\n",
    "    'OverallCond',\n",
    "    'YearRemodAdd',\n",
    "    'RoofStyle',\n",
    "    'Exterior1st',\n",
    "    'ExterQual',\n",
    "    'Foundation',\n",
    "    'BsmtQual',\n",
    "    'BsmtExposure',\n",
    "    'BsmtFinType1',\n",
    "    'HeatingQC',\n",
    "    'CentralAir',\n",
    "    '1stFlrSF',\n",
    "    '2ndFlrSF',\n",
    "    'GrLivArea',\n",
    "    'BsmtFullBath',\n",
    "    'HalfBath',\n",
    "    'KitchenQual',\n",
    "    'TotRmsAbvGrd',\n",
    "    'Functional',\n",
    "    'Fireplaces',\n",
    "    'FireplaceQu',\n",
    "    'GarageFinish',\n",
    "    'GarageCars',\n",
    "    'GarageArea',\n",
    "    'PavedDrive',\n",
    "    'WoodDeckSF',\n",
    "    'ScreenPorch',\n",
    "    'SaleCondition',\n",
    "    # this one is only to calculate temporal variable:\n",
    "    \"YrSold\",\n",
    "]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "((1314, 37), (146, 37))"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X_train = X_train[FEATURES]\n",
    "X_test = X_test[FEATURES]\n",
    "\n",
    "X_train.shape, X_test.shape"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Pipeline - End-to-end\n",
    "\n",
    "We have 3 steps less, they are commented out. So the pipeline is also simpler:\n",
    "\n",
    "- the yeo-johnson transformation\n",
    "- 1 of the mappings\n",
    "- the selection procedure\n",
    "\n",
    "this makes the pipeline faster and easier to deploy."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "# set up the pipeline\n",
    "price_pipe = Pipeline([\n",
    "\n",
    "    # ===== IMPUTATION =====\n",
    "    # impute categorical variables with string missing\n",
    "    ('missing_imputation', CategoricalImputer(\n",
    "        imputation_method='missing', variables=CATEGORICAL_VARS_WITH_NA_MISSING)),\n",
    "\n",
    "    ('frequent_imputation', CategoricalImputer(\n",
    "        imputation_method='frequent', variables=CATEGORICAL_VARS_WITH_NA_FREQUENT)),\n",
    "\n",
    "    # add missing indicator\n",
    "    ('missing_indicator', AddMissingIndicator(variables=NUMERICAL_VARS_WITH_NA)),\n",
    "\n",
    "    # impute numerical variables with the mean\n",
    "    ('mean_imputation', MeanMedianImputer(\n",
    "        imputation_method='mean', variables=NUMERICAL_VARS_WITH_NA\n",
    "    )),\n",
    "    \n",
    "    \n",
    "    # == TEMPORAL VARIABLES ====\n",
    "    ('elapsed_time', pp.TemporalVariableTransformer(\n",
    "        variables=TEMPORAL_VARS, reference_variable=REF_VAR)),\n",
    "\n",
    "    ('drop_features', DropFeatures(features_to_drop=[REF_VAR])),\n",
    "\n",
    "   \n",
    "\n",
    "    # ==== VARIABLE TRANSFORMATION =====\n",
    "    ('log', LogTransformer(variables=NUMERICALS_LOG_VARS)),\n",
    "    \n",
    "#     ('yeojohnson', YeoJohnsonTransformer(variables=NUMERICALS_YEO_VARS)),\n",
    "    \n",
    "    ('binarizer', SklearnTransformerWrapper(\n",
    "        transformer=Binarizer(threshold=0), variables=BINARIZE_VARS)),\n",
    "    \n",
    "\n",
    "    # === mappers ===\n",
    "    ('mapper_qual', pp.Mapper(\n",
    "        variables=QUAL_VARS, mappings=QUAL_MAPPINGS)),\n",
    "\n",
    "    ('mapper_exposure', pp.Mapper(\n",
    "        variables=EXPOSURE_VARS, mappings=EXPOSURE_MAPPINGS)),\n",
    "\n",
    "    ('mapper_finish', pp.Mapper(\n",
    "        variables=FINISH_VARS, mappings=FINISH_MAPPINGS)),\n",
    "\n",
    "    ('mapper_garage', pp.Mapper(\n",
    "        variables=GARAGE_VARS, mappings=GARAGE_MAPPINGS)),\n",
    "    \n",
    "#     ('mapper_fence', pp.Mapper(\n",
    "#         variables=FENCE_VARS, mappings=FENCE_MAPPINGS)),\n",
    "\n",
    "\n",
    "    # == CATEGORICAL ENCODING\n",
    "    ('rare_label_encoder', RareLabelEncoder(\n",
    "        tol=0.01, n_categories=1, variables=CATEGORICAL_VARS\n",
    "    )),\n",
    "\n",
    "    # encode categorical and discrete variables using the target mean\n",
    "    ('categorical_encoder', OrdinalEncoder(\n",
    "        encoding_method='ordered', variables=CATEGORICAL_VARS)),\n",
    "    \n",
    "    \n",
    "    ('scaler', MinMaxScaler()),\n",
    "#     ('selector', SelectFromModel(Lasso(alpha=0.001, random_state=0))),\n",
    "    ('Lasso', Lasso(alpha=0.001, random_state=0)),\n",
    "])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Pipeline(steps=[('missing_imputation',\n",
       "                 CategoricalImputer(variables=['FireplaceQu'])),\n",
       "                ('frequent_imputation',\n",
       "                 CategoricalImputer(imputation_method='frequent',\n",
       "                                    variables=['BsmtQual', 'BsmtExposure',\n",
       "                                               'BsmtFinType1',\n",
       "                                               'GarageFinish'])),\n",
       "                ('missing_indicator',\n",
       "                 AddMissingIndicator(variables=['LotFrontage'])),\n",
       "                ('mean_imputation',\n",
       "                 MeanMedianImputer(imputation_method=...\n",
       "                                             'Foundation', 'CentralAir',\n",
       "                                             'Functional', 'PavedDrive',\n",
       "                                             'SaleCondition'])),\n",
       "                ('categorical_encoder',\n",
       "                 OrdinalEncoder(variables=['MSSubClass', 'MSZoning', 'LotShape',\n",
       "                                           'LandContour', 'LotConfig',\n",
       "                                           'Neighborhood', 'RoofStyle',\n",
       "                                           'Exterior1st', 'Foundation',\n",
       "                                           'CentralAir', 'Functional',\n",
       "                                           'PavedDrive', 'SaleCondition'])),\n",
       "                ('scaler', MinMaxScaler()),\n",
       "                ('Lasso', Lasso(alpha=0.001, random_state=0))])"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# train the pipeline\n",
    "price_pipe.fit(X_train, y_train)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "train mse: 781396630\n",
      "train rmse: 27953\n",
      "train r2: 0.8748530315439078\n",
      "\n",
      "test mse: 1060769014\n",
      "test rmse: 32569\n",
      "test r2: 0.8456415571208442\n",
      "\n",
      "Average house price:  163000\n"
     ]
    }
   ],
   "source": [
    "# evaluate the model:\n",
    "# ====================\n",
    "\n",
    "# make predictions for train set\n",
    "pred = price_pipe.predict(X_train)\n",
    "\n",
    "# determine mse, rmse and r2\n",
    "print('train mse: {}'.format(int(\n",
    "    mean_squared_error(np.exp(y_train), np.exp(pred)))))\n",
    "print('train rmse: {}'.format(int(\n",
    "    mean_squared_error(np.exp(y_train), np.exp(pred), squared=False))))\n",
    "print('train r2: {}'.format(\n",
    "    r2_score(np.exp(y_train), np.exp(pred))))\n",
    "print()\n",
    "\n",
    "# make predictions for test set\n",
    "pred = price_pipe.predict(X_test)\n",
    "\n",
    "# determine mse, rmse and r2\n",
    "print('test mse: {}'.format(int(\n",
    "    mean_squared_error(np.exp(y_test), np.exp(pred)))))\n",
    "print('test rmse: {}'.format(int(\n",
    "    mean_squared_error(np.exp(y_test), np.exp(pred), squared=False))))\n",
    "print('test r2: {}'.format(\n",
    "    r2_score(np.exp(y_test), np.exp(pred))))\n",
    "print()\n",
    "\n",
    "print('Average house price: ', int(np.exp(y_train).median()))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Identical results to when we did all the engineering manually."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0.5, 1.0, 'Evaluation of Lasso Predictions')"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAY4AAAEWCAYAAABxMXBSAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8QVMy6AAAACXBIWXMAAAsTAAALEwEAmpwYAAAyzElEQVR4nO3deZxcZZ3v8c83SQPNoh0kcklLCC4TF5AE+gIjjgqOgIgaQEQGFZQRvTPMHdSJgjgSRmdEo6Ijd0ZRGfXKYFQgsmmIgqJcURMSlkiigCB0kARJy5JWOsnv/nFONdXV51Sd6qrqqu7+vl+venXVU2d56nT3+dWzKyIwMzMralq7M2BmZhOLA4eZmdXFgcPMzOriwGFmZnVx4DAzs7o4cJiZWV0cOGxcSPqRpL9t0bE/JOnLrTh2jfMeJ+kBSU9IWjDe5+9E5b9nSadIun6Mx/mepFObmztrFgcOG0HSfZIG05th6XFRu/NVIulVkh4sT4uIf4uIlgSlGj4FnBkRu0bE6so3JYWk57chX1Wl+Xoy/d32S/qMpOnNPk9EXBoRRxbIz2JJ36jY97UR8bVm58maY0a7M2Ad6fUR8YN2Z2IC2AdY2+5MjNEBEXG3pBcCPwJ+DXyhfANJMyJiazsyZ53NJQ4rRNKOkgYk7VeWNistnTxb0kxJ10jaJGlz+vw5Occa8Q1T0tz0W/CM9PU7JN0l6XFJ90p6d5q+C/A9YHZZaWh2xvHeIGltmt8fSXpR2Xv3SfonSbdL+qOkpZJ2ysnnNEkflnS/pI2Svi7pmem1eAKYDtwm6Z46r+XzJN0g6Q+SHpF0qaSesvc/mJYEHpe0XtKr0/SDJa2U9JikhyV9pshnriYi1gE/AfYr+z2cLul3wA3psd+Z/j42S1ouaZ+y875G0rr0Wl4EqOy90yT9tOz1SyStkPRomv8PSToa+BBwUvr7vC3dtrzKK/P3kL5XyvOpkn6XXs9zy86Ze81s7Bw4rJCI+DNwBXByWfKbgR9HxEaSv6X/IvkWPgcYBMZaxbUROBZ4BvAO4EJJB0bEk8BrgQ1p9dCuEbGhfEdJfwFcBpwFzAKuA66WtENFvo8G9gVeCpyWk4/T0sfhwHOBXYGLIuLPEbFrus0BEfG8Oj+fgI8Ds4EXAXsDi9P8zwPOBP5nROwGHAXcl+73OeBzEfEM4HnAt+r4zNkZkV4M/BVQXtX2yjRfR0l6I8mN/fj02D9Jz4WkPUj+Jj4M7AHcAxyWc57dgB8A308/9/OBH0bE94F/A5amv88DMnY/jYzfQ8U2LwfmAa8GPlIWODOvmTXGgcOyLEu/uZYe70rT/xt4S9l2f5OmERF/iIjLI2JLRDwO/CvJDahuEXFtRNwTiR8D15Pc3Io4Cbg2IlZExBBJO0Q38LKybf49IjZExKPA1cD8nGOdAnwmIu6NiCeAc4C3lEpGYxURd6f5+3NEbAI+w9PXahuwI/BiSV0RcV9ElEo0Q8DzJe0REU9ExC11fOZKt0raTPL5v0wS9EsWR8STETEIvAf4eETclVZb/RswPy11HAOsjYjvpOf9LPD7nPMdC/w+Ij4dEX+KiMcj4ufFrlih38P5ETEYEbcBtwGlAJR3zawBDhyWZWFE9JQ9vpSm3wjsLOkQSXNJbrhXAkjaWdIX0+qEx4CbgB6NodFV0msl3ZJWaQyQ3KD2KLj7bOD+0ouI2A48APSWbVN+c9tC8g225rHS5zOAPQvmJZOkPSV9M62Oegz4Bunni4i7SUoOi4GN6Xaz011PB/4CWCfpl5KOzcpnzmeudGBEzIyI50XEh9N9Sh4oe74P8LnSlwjgUZISU2963uFtI5kxtXzfcnuTlEjGosjvIe93mnfNrAEOHFZYRGwjKeqfnD6uSUsXAO8nqSo4JK0WeEWarlEHgieBncte/4/SE0k7ApeTfGveMyJ6SKpeSsepNZ3zBpKbXel4Irlp9dfYr+axSKrgtgIPj+FY5f6N5HPsn16rt1J2nSLivyPi5em5A/hEmv6biDgZeHaa9h0l7T7N/Mww8ho/ALy74otEd0T8P+Ch9DyV583yAEk1U63zZRnz76HKNbMGOHBYvf6bpGrklPR5yW4k7RoDknYHzqtyjDXAKyTNSRs5zyl7bweSqppNwFZJrwXKu3Q+DDyr1Dia4VvA6yS9WlIXSUD7M/D/Cn6+cpcB75W0r6Rdebouvp6eRjtI2qnsMZ3kWj0B/FFSL7CotLGkeZKOSAPon0iu6fb0vbdKmpWWDgbSXbY3+TNX+gJwjqSXpHl4pqQT0/euBV4i6fi02uh/U/YloMI1wF6SzlLSuWA3SYek7z0MzJWUdz8a8++hyjWzBjhwWJarNXIcx5WlN9J66SdJqg++V7bPZ0nq1R8BbiFpBM0UESuApcDtwCqSm0rpvcdJbkDfAjaTtKNcVfb+OpIbyb1p9cnsskMTEetJvsF/Ps3L60m6Fz9V5zUAuAT4vyTVbr8luZH/Q53HWEty8y893gGcDxwI/JHk5ntF2fY7Ahekef89yTflUmA9GlirpEfX54C3pPX6zfzMI0TElSTf1L+ZVqvdSdJBgYh4BDgxze8fgBcAN+cc53HgNWnefg/8hqSxG+Db6c8/SLo1Y/dGfg+Z16zgvpZDXsjJzMzq4RKHmZnVxYHDzMzq4sBhZmZ1ceAwM7O6TIlJDvfYY4+YO3duu7NhZjahrFq16pGImFWZPiUCx9y5c1m5cmW7s2FmNqFIuj8r3VVVZmZWFwcOMzOriwOHmZnVxYHDzMzq4sBhZmZ1mRK9qszMppplq/tZsnw9GwYGmd3TzaKj5rFwQbUlWopz4DAzm2SWre7nnCvuYHBoGwD9A4Occ8UdAE0JHq6qMjObZJYsXz8cNEoGh7axZPn6phzfgcPMbJLZMJC95Eheer0cOMzMJpnZPd11pdfLgcPMbJJZdNQ8urumj0jr7prOoqPmNeX4bhw3M5tkSg3g7lVlZmaFLVzQ27RAUamlVVWSLpG0UdKdZWkflXS7pDWSrpc0O2ffUyX9Jn2cWpZ+kKQ7JN0t6d8lqZWfwczMRmp1G8dXgaMr0pZExEsjYj5wDfCRyp0k7Q6cBxwCHAycJ2lm+vZ/Au8CXpA+Ko9vZmYt1NLAERE3AY9WpD1W9nIXIDJ2PQpYERGPRsRmYAVwtKS9gGdExC0REcDXgYUtybyZmWVqSxuHpH8F3g78ETg8Y5Ne4IGy1w+mab3p88r0rHOcAZwBMGfOnMYzbWZmQJu640bEuRGxN3ApcGaLznFxRPRFRN+sWaNWPjQzszFq9ziOS4ETMtL7gb3LXj8nTetPn1emm5nZOBn3wCHpBWUv3wisy9hsOXCkpJlpo/iRwPKIeAh4TNKhaW+qtwPfbXmmzcxsWEvbOCRdBrwK2EPSgyQ9pY6RNA/YDtwPvCfdtg94T0T8bUQ8KumjwC/TQ/1LRJQa2f+OpLdWN/C99GFmZuNESeekya2vry9WrlzZ7myYmU0oklZFRF9lervbOMzMbIJx4DAzs7o4cJiZWV08yaGZjatWroVt48OBw8zGTavXwrbx4aoqMxs3rV4L28aHSxxmNm6KroXt6qzO5hKHmY2bImthl6qz+gcGCZ6uzlq22rMLdQoHDjMbN0XWwnZ1VudzVZWZjZsia2EXrc6y9nHgMLNxVWst7Nk93fRnBIm8ai4bf66qMrOOUqQ6y9rLJQ4z6yhFqrOsvRw4zKzj1KrOsvZyVZWZmdXFJQ4z60geBNi5HDjMrON4TqvO5qoqM+s4HgTY2VoWOCRdImmjpDvL0pZIWifpdklXSurJ2G+epDVlj8cknZW+t1hSf9l7x7Qq/2bWPh4E2NlaWeL4KnB0RdoKYL+IeCnwa+Ccyp0iYn1EzI+I+cBBwBbgyrJNLiy9HxHXtSTnZtZWRea0svZpWeCIiJuARyvSro+IrenLW4Dn1DjMq4F7IuL+FmTRzDqUBwF2tnY2jr8TWFpjm7cAl1WknSnp7cBK4P0RsbkVmTOz8VXZi+qEg3q5cd0m96rqQIqI1h1cmgtcExH7VaSfC/QBx0dOBiTtAGwAXhIRD6dpewKPAAF8FNgrIt6Zs/8ZwBkAc+bMOej++11oMetUlb2oIClhfPz4/R0s2kjSqojoq0wf915Vkk4DjgVOyQsaqdcCt5aCBkBEPBwR2yJiO/Al4OC8nSPi4ojoi4i+WbNmNSn3ZtYK7kU1sYxrVZWko4EPAK+MiC01Nj+ZimoqSXtFxEPpy+OAO0ftZWYNG+/Bd+5FNbG0sjvuZcDPgHmSHpR0OnARsBuwIu1O+4V029mSrivbdxfgNcAVFYf9pKQ7JN0OHA68t1X5N5uq2rECn3tRTSwtK3FExMkZyV/J2XYDcEzZ6yeBZ2Vs97amZdDMMlWrNmpVqWPRUfMy2zjci6ozecoRMxuhHdVGnkp9YnHgMLMR2rUCn6dSnzg8V5WZjeDBd1aLSxxmNoKrjawWBw6zDtBpa0+42siqKVRVJenlkt6RPp8lad/WZsts6mhH91ezRtQMHJLOAz7I0zPZdgHfaGWmzKaSyTxqetnqfg674Ab2PftaDrvgBgfDSaJIVdVxwALgVkjGXEjaraW5MptCJuuoaa/iN3kVqap6Kp1TKmB4VLeZNclkHTU9mUtSU12RwPEtSV8EeiS9C/gByQSDZtYEjXZ/7dTqoMlakrICVVUR8SlJrwEeA+YBH4mIFS3PmdkU0Uj3106uDmrXQEJrvZqBI+1B9ZNSsJDULWluRNzX6syZTRVj7f7ajnmlivL8U5NXkaqqbwPby15vS9PMrM06uTpo4YJePn78/vT2dCOgt6fbCzNNEkV6Vc2IiKdKLyLiqXR1PjNrs56du9i8ZWhUeqdUB3kg4eRUpMSxSdIbSi8kvZFk+VYza6Nlq/t54k9bR6V3TZerg6ylipQ43gNcKukiQMADwNtbmiszq2nJ8vUMbR+9+vIuO8wY87f8Tpv6xDpTkV5V9wCHSto1ff1Ey3NlZjXltWP8cXB01VURndxDyzpLbuCQ9NaI+Iak91WkAxARn2lx3sysimZ3d+3kHlrWWaq1cZRGiO+W8zCzNmr2uhmd3EPLOktuiSMivihpOvBYRFxY74ElXQIcC2yMiP3StCXA64GngHuAd0TEQMa+9wGPk3T93RoRfWn67sBSYC5wH/DmiNhcb97MJoNmr5vhAXtWlJJpqKpsIP0iIg6u+8DSK4AngK+XBY4jgRsiYqukTwBExAcz9r0P6IuIRyrSPwk8GhEXSDobmJm1f6W+vr5YuXJlvR/BbEqpbOOApATjsRdTl6RVpS/u5Yr0qro57VG1FHiylBgRt1bbKSJukjS3Iu36spe3AG8qcP5ybwRelT7/GvAjkinfzSadrB5O0LqV+bzynxVVpMRxY0ZyRMQRNQ+eBI5rSiWOiveuBpZGxKi1PST9FthMMiPvFyPi4jR9ICJ60ucCNpdeZxzjDOAMgDlz5hx0//3318quWcfI+vbfNU0gGNr29P/sRC4RuOtv52ukxHFiZZVREzJzLrAVuDRnk5dHRL+kZwMrJK2LiJvKN4iIkJQb9dJgczEkVVVNyrpZpkZugln7ZvVwyhqz0exeT+N1M3fX34ktt1eVpNdL2gTcLulBSS9rxgklnUbSaH5K5BR3IqI//bkRuBIotbE8LGmv9Dh7ARubkSezRjSy9GvevlmN1Hma1etpPJew9VodE1u17rj/CvxVRMwGTgA+3ujJJB0NfAB4Q0Rsydlml9IKg+miUUcCd6ZvXwWcmj4/Ffhuo3kya1QjN8G8faen46WKKPV6anRdjvG8mbvr78RWLXBsjYh1ABHxc+ocuyHpMuBnwLy0xHI6cFF6nBWS1kj6QrrtbEnXpbvuCfxU0m3AL4BrI+L76XsXAK+R9Bvgr9PXZm3VyE0wb5ttEaPGaHRNE13TRwaU0riNZpQWxvNmPllXPZwqqrVxPLti1PiI17VGjkfEyRnJX8nZdgNwTPr8XuCAnO3+ALy62nnNaml2PX4j4x/y9u0ta+so0qvqsAtuaHjU93iO4/BaHRNbtcDxJUaWMipfm004rWiUbeQmWG3fvCnJs9KaUVoYz5u5u/5ObNVGjp8/nhkxGw+tmI+pkZtgs26gzSgtjPfN3Gt1TFw1x3FMBh45biX7nn0tWX/xAn57wevGOztN41Hf1gp54ziKLORkNmlM1kZZL9Nq46nIAECzSWMyN8q66sfGS80Sh6Q9JX1F0vfS1y9Ou9aaTTj+Zm7WuCIljq8C/wWcm77+NcmEh5lda806nb+ZmzWmSODYIyK+JekcgHRK9G21djKzxngSQOtURRrHn5T0LJKZapF0KPDHlubKbIrLGgl+1tI1zD//+pbMHWVWjyIljveRzBH1PEk3A7Oofx0NM6N4KSJrvAnAwOCQZ5G1tqsZOCLiVkmvBOaRdHdfHxFDLc+Z2QRULTDUM2q92ojvZk+lblavmoFD0onA9yNiraQPAwdK+litFQDNJrvKIHH4C2dx+ar+3MBQz6j1vJHgJZ5F1tqpSBvHP0fE45JeTjLB4FeA/2xttsxaq9EpyLPaIC695XdVpyWvZz6pRUfNGzU7brnZPd0NfwazsSrSxlH6T3gd8KWIuFbSx1qYJ7OWqlZlBMXmasoqPeRN3lMKDPXMJ1U65/lXr2XzlpE1w91d0zn8hbO8gp61TZESR7+kLwInAddJ2rHgfmYdKa/KaPFVawuvaVFPVVEpMGSVIqqNWl+4oJfVHzmSz540f9SAxRvXbfIKetY2RUocbwaOBj4VEQPpkq2LWpsts9bJu+kPDI7u81F+My4vifTs3DWqJJCla5qGA8NYZ5/NGrD43qVrMrd124eNhyIlhz2AlcCfJc0BuoB1Lc2VWZlm1+XXO6Fh+TrgpZLIE3/aOmo1viy77jRjxE1/4YJebj77CC48aT6QBICxfKbJOlmjTQxFShzXklTfCtgJ2BdYD7ykhfkyA5q78FKpF1T/wCBiZJtEd9d0RLBlaHvmvpXVQkPbk72nCbZXWZlgIKNU0ozPNJkna7TOV7PEERH7R8RL058vAA4mWUu8KkmXSNoo6c6ytCWS1km6XdKVknoy9ttb0o2SfiVpraR/LHtvsaT+dL3yNZKOKfxJbUKq1oW1HuW9oODpb0LwdLvBjlV6MeXZHtA1XfR0d2W+n1UCaMZn8mSN1k51T6ueDgg8pMCmXwUuAr5elrYCOCed7+oTwDnAByv22wq8Pz3PbsAqSSsi4lfp+xdGxKfqzbdNTLW6sDYyEjtIbrg3n30EkN9uUMvQtkBKvvEXKQE0Y5lX8GSN1j5FplV/X9njnyT9N7Ch1n4RcRPwaEXa9RGxNX15C/CcjP0eKg0ujIjHgbsA/3dMUdXq8rPGUtTbC6o8vVr7QK3WjIEtQ4VLAG6fsImuSOP4bmWPHUnaPN7YhHO/E/hetQ0kzQUWAD8vSz4zreq6RNLMKvueIWmlpJWbNm1qQnatHap1Ya2nyqfIzXrRUfMyG7y7polTDp3DdOWHj9k93Sxc0Muio+Yxu6ebDQODLFm+PjOI1dst16zTFGnjOD8izgc+DXwuIi6NiD81clJJ55JUSV1aZZtdgcuBsyLisTT5P4HnAfOBh9I85eX74ojoi4i+WbNmNZJda6NqdfmNjsSuvFkvXNDLkjcdwMydn26v6OnuYsmJB/Cxhftz6HOzv6coPX7REpDbJ2yiKzJX1X7A/wV2T18/ApwaEXdW3TH/eKcBxwKvjojM/iiSukiCxqURcUUpPSIeLtvmS8A1Y8mDTSx5dfljGYldqz2kWrvBLfduzs6gkv0Ou+CGwnNRuX3CJrIijeMXA++LiBsBJL0qTXtZvSeTdDTwAeCVEbElZxuRzId1V0R8puK9vSLiofTlccCYgpdNDkW6pC5b3T9i2o6e7i4uPGk+Cxf0Do8PKQ8kkB9ctmV/z6GU3KxGb7NOVyRw7FIKGgAR8SNJu9TaSdJlwKuAPSQ9CJxH0otqR2BFEh+4JSLeI2k28OWIOAY4DHgbcIekNenhPhQR1wGflDSfpEPMfcC7i3xIm5xqlSKWre5n0XduY2jb0zf8gcEhzlq6hrMqelD1DwzyvqVrmD5dw9tXjq+YLmUGj1LbRz0lILOJrEjguFfSP5NUVwG8Fbi31k4RcXJGcuY65RGxATgmff5TcjqxRMTbCuTXppDK4FFqGC9NY14eNGrZDmyv2L68qunkQ/bmG7f8btR+Jx+yN+BBeTZ1FAkc7wTOB0ptDT9J08zGXT1rYFRbz6Iepaqmjy3cH4DLfv4A2yKYLnHyIXsPp491LiqziUY57dOTSl9fX6xcubLd2bAGVU7VAYyaOqSku2safxranjvVeT3KBwmaTSWSVkVEX2V6bolD0tXkLzFARLyhSXkzK6SeNTAGc+acqlfXdLmqyaxCtaqq0rQeAr4E/G3rs2OWry29kyZ/gdysbrmBIyJ+XHou6Yny12btUGsd7lYY2h6Z4zDMprKiK/n5e5e1TNH1NvJGf++yQ/astrVXyyjG4zDMRqrWxrF72cvp6bxQw/+LEfHo6L3M6lPP2hR5vZaAzG6wJxzUO9wDqhHPzJky3Wyqyu1VJem3jFy2oFxExHNbmbFmcq+qznXYBTdkVj/V25Mpa4T44jcka41VBpV6TVMyOtzda22qyetVlVtVFRH7RsRz05+VjwkTNKyzNXOajj+V9aQaGBzivUvXsPL+R0dMKDgW24Oa07abTSVF2zjMWqJZa1PkddW9NB3pffPZR/DbC15Hb5XjVps2vWQsqw+aTTYOHNZWi46aR9e0kTfsrmn1j53IK6EEDN/ol63uZ8tTW0dt0901nc+eNJ9Pv/mAUY3v9ZzLbKqoe+lYs6ar/KKf8cW/1hKx1brqbhgYzBx1Dk+3hZQfq3SeaTmTGnrSQpvqckscknav9hjPTNrklTUR4dC2GFEdVGSBpEVHzcttw5jd051ZlQWwy44zRgSNhQt6h6u1skognrTQrHpV1SpgZfpzE/Br4Dfp81Wtz5pNBUUax4suEbtzxniO0o1+LI3wXqnPLFu1keP7wvBKe1em62Eg6bXAwnHJnU16RdawqHXTz6uGAtipa1rh82TxSn1moxVpHD+0FDQAIuJ7jGH1P7OsEeJZo8EFHP7Cp9eJr9XzKq8aCmDzliHOueIODn/hLFc7mTVJkcCxQdKHJc1NH+cCG1qdMZtc8topAE44qHdE+0QAl6/qH27DyJtqpHTTr9XLaXBoG5f9/AEGh7YNd7l1tZPZ2BXpVXUyybKvV5L8T9+UppkVVqudorLv0uDQNt7/rduA2gskFZn8sNQ7alvEcNBx0DAbm8ILOUnaJSKerOvg0iXAscDGiNgvTVsCvB54CrgHeEdEDGTsezTwOWA6yXrkF6Tp+wLfBJ5F0kj/toh4qlo+POVI++179rWZM2WWShp5f4XdXdNHlAyyuuVC/dOKeHEms9rqnnKkbMeXSfoVcFf6+gBJ/1HwvF8Fjq5IWwHsFxEvJempdU7GOacD/wd4LfBi4GRJL07f/gRwYUQ8H9gMnF4wL9Ymy1b3My1nVPbsnu6qDdTlpZJq1V2l3k9FeRCf2dgVaeO4EDgK+ANARNwGvKLIwSPiJuDRirTrI6I0fPcW4DkZux4M3B0R96aliW8Cb5Qk4AjgO+l2X8M9vDrWstX9zD//es5auiZzIF2pyqi8ITxLqRqqWnVXafxF0eDhQXxmY1do5HhEPKCR3xjHPtXoSO8Elmak9wIPlL1+EDiEpHpqoCzwPJhuax2mWhdZSOaFKlVB1Zr7qdSgnVdK6B8Y5LALbmBDWhKpxb2pzBpTJHA8IOllQEjqAv6RtNqqEWnvrK3ApY0eK+f4ZwBnAMyZM6cVpzDypwKp1kUWYHvEcLtFrWqjUmklrxFcUHhlwF5PjW7WsCKB4z0kjdS9QD9wPfB3jZxU0mkkjeavjuzW+X5g77LXz0nT/gD0SJqRljpK6aNExMXAxZA0jjeSX8tWbRGmWsFgmsS+Z1/L7J5untndxcDgUO62peqnRUfNyyzF1PrlCjjl0Dl8bOH+NbY0syKKBI55EXFKeYKkw4Cbx3LCtLfUB4BXRsSWnM1+Cbwg7UHVD7wF+JuICEk3Am8iafc4FfjuWPJhjavW5lCri2ypFNE/MEjXdNE1TQxtz28HgdHdcnt27hpeuCmLYETPq1J1lhdkMmtMkcbxzxdMG0XSZcDPgHmSHpR0OnARsBuwQtIaSV9It50t6TqAtDRxJrCcpFrsWxGxNj3sB4H3SbqbpM3jK0XyYs1Xrc0ha9AeJKvpVRraFuy604zhkkW1QXrlkxDuvEP+957enm5+e8Hrhrvc1pokEYqvfW421VVbc/wvSaYWmSXpfWVvPYNkbEVNEZE1UDDzRh8RG4Bjyl5fB1yXsd29JL2urEytacdboVqbAyRdZCvz9N6lazKPNbBliNUfObKu81erDitv/K7VGwvqW/vcbKqrVlW1A7Brus1uZemPkVQVWYcYz5teeYB6ZndX5jYBnLV0TWZD9JLl68c02WCWvMA1c+euEedsdAZeBw6zkaqtOf7jiDifZJLD88sen4mI34xjHq2GotOON6pyAF61Bm3IXzejWZMN5h3rvNe/ZERakeVpm7n2udlkV6SN48uSekovJM2UtLx1WbJ6jddNr1YX2yylOadKwaOZa1wUPVaRYNWstc/NpoIivar2KJ9LKiI2S3p267Jk9RrrWhP1Gmsg2hYxouosb42LsbTTFFkvo9YkiZDd1dcDBc2yFQkc2yXNiYjfAUjah9pd520cjddNr8gstHmyZrst1+p2mloBpkhwMbNEkcBxLvBTST8m6TDzV6Qjsq0z1HvTG2sPrLwBeEVVljzKdULjtFf7MyumZuCIiO9LOhA4NE06KyIeaW22rF5Fb3qNfLOvDFDTpMzJC6vJCwZ5JZn+gUGWre73Dd2sg+Q2jkt6YfrzQGAOyap/G4A5aZpNQI32wCofgFdv0CipbCtZtrqf7EnXE1mD9cysfaqVON4PvAv4dMZ7QTK9uU0wzeqBVbrZjyV0VDbaL1m+vupxPJ7CrLPkBo6IeFf68/Dxy4612lh6YGW1idS62efJarQvErRKU6e7wdqs/apNOXJ8tR0j4ormZ8daLauBW5C7mFJem8hYGsjL1+AoV7S3lqcBMesM1QYAvj59nE4yv9Qp6ePLJAsw2QS0cEEvJxzUO6JNIYDLV/VntiPktYnkKQ3Gy5LXJpI3IWKWVoyIN7P6VKuqegeApOuBF0fEQ+nrvUjWErcJ6sZ1m0ZVM+W1I9TT9iEYrsbKK0Es+vZtnH/1Wga2DI3qClw+B5ZE7pTpngbErL2KjOPYuxQ0Ug+T9LKyCaqeBvJ6Bv0F8N6la3hmdxdd08XQttEljKHtMRwQKqueKoPWYRfcMC4j4s2sPkXmqvqhpOWSTktX7rsW+EFrs2WtVM+8TFnVSNW6zg5Pfliw5bxa1VMzJ0Q0s+apGTgi4kzgC8AB6ePiiPiHVmfMWmfRUfPoqlhRqWuaRt2QS72pBoe2jVhc6ZRD59RskxjaHsP71JJXAmrmhIhm1jxFqqoAbgUej4gfSNpZ0m4R8XgrM2YtVnlPr3hd2ZtqW8Twt/2FC3rp22f34TaJvMLFtojcJWHLVat68jQgZp2nZolD0ruA7wBfTJN6gWUtzJMVNNalTpcsXz+q/WFoW4yoMqo1wrx8BHlvzo2/p7urer0Wrnoym4iKtHH8PXAYycp/pIs4eVr1NqtcVKl/YJCzlq5hwb9cXzWALFvdn9vYXV5lVE8Del5bhERmA/l0yVVPZhNYkaqqP0fEU0rrqyXNoEDTp6RLgGOBjRGxX5p2IrAYeBFwcESszNhvHrC0LOm5wEci4rOSFpNMg7Ipfe9D6drkU07eokqbtwyx6Du3sfiqtfxxcGSX12Wr+1n0ndtyjzlNYt+zr2V2Tzc9O3dldofNqlbKm503b33x7RH89oLXFfykZtZpigSOH0v6ENAt6TXA3wFXF9jvq8BFwNfL0u4Ejufpaq9RImI9MB9A0nSgH7iybJMLI+JTBc4/qVUbyzC0LYaXdS3v8ppVRVWuNECvf2CQrmka1aW2WrVSVltEM9cXN7POUaSq6oMk3/DvAN4NXAd8uNZOEXET8GhF2l1pYCjq1cA9EXF/HftMCfXcfEttE/UMnBvaHuyyw4zcHk1F2lfcndZscqpa4ki/8a+NiBcCXxqfLI3wFuCyirQzJb0dWAm8PyI2Z+0o6QzSBafmzJl84xXrXVSpVIVUzwp+fxwcYs15R45Kr7amB4yssjrhoF5uXLep4VX1xrr4lJk1n6LGmgqSvgv8Q2np2LoOLs0Frim1cZSl/wj4p6w2jrJtdiBZ/+MlEfFwmrYn8AhJG8tHgb0ioua8WX19fbFyZe6pJqxlq/tZfNXa4WqpanrTm+2i79xWtbqqcp+bz3569vzSzTsv+MzcuYs/DW0ftYRtow3glYGqWcc1s+okrYqIvsr0IlVVM4G1kn4o6arSo/lZHOW1wK2loAEQEQ9HxLaI2E5SAjp4HPLRsRYu6GXNeUfy2ZPmD1cpzdy5a9TgvvLxF0vedAAzd+4afq+nu4u3HjqHrukVAwKnjxwQWN6LK8/mLUMNLRKVp9HFp8ysuYo0jv9zy3OR7WQqqqkk7VU2b9ZxJI3tU15lw3S1ap2sRuxlq/tZ+osHRh60olCS14uriEYnJWzW4lNm1hzV1uPYCXgP8HyShvGvRMTWogeWdBnwKmAPSQ8C55E0ln8emAVcK2lNRBwlaTbw5Yg4Jt13F+A1JI3x5T4paT7Jbe2+jPeN+kdbL1m+ftTo7qHtweKr1tYcHV5Eo72oxrL4lJm1TrUSx9eAIeAnJNVGLwb+seiBI+LknLeurEyIiA3AMWWvnwSelbHd24qef6pppPE475v7wOBQofaTarLmwKpXVkcA984ya59qgePFEbE/gKSvAL8YnyxZvar1cioSPOrtbVWPXXea0XADdt4AQzeMm7VHtcAx/FUzIraq4EynNv6qNR4XubkuOmoei759W83JCMdiIGcxpnp5skOzzlGtV9UBkh5LH48DLy09l/TYeGXQamu08Xjhgl523anYRMnl3x9Knbd6e7pH9NQq53YIs8mn2tKxxRaBtrarp/E4ry2kaMmgfNjPjjOeHkuRN9bC7RBmk0+RcRzW4YpO7ZE1o+45V9zBstX99OSUGKqpnGbdiy6ZTQ1FF3KyDla08TivLeT8q9fyxJ8K97Qeobw6zO0QZlODA8ckUeSmndfmkTV9ermZO3cRQWbXXLdhmE09rqqaQsZ6k995hxksfsNLPNOtmQEOHFNKXltIT3f19o0NA4NuwzCzYa6qmkIWLuhl5f2PctnPH2BbBNMlTjiol759dq86RXuppOI2DDMDlzgmpCKLKOXtd/mq/uGV/rZFcPmqZN+PH79/5lgMV0eZWSWXOFqs2QsQNTK9SLUR5jeffcTweAxP7WFm1ThwtFCjc0hlaWR6kSIjzF0dZWa1uKqqhVqxAFEj04vk9apyl1ozq4cDRwu1YgGiRm7+RUeYm5lV48DRgFqN1K34ht/Izd9das2sGdzGMUZF2i9atQDRjjOmDR9z565p7Ng1jfcuXcOS5etrNma7DcPMGuXAMUZFGqmbvQBR1gy0W4a2s2VoO5AdvNxLysyarWWBQ9IlwLHAxojYL007EVgMvAg4OCJW5ux7H/A4sA3YGhF9afruwFJgLsma42+OiM2t+gzVFG2/aOY3/KxgVak8eLWiV5eZWSvbOL4KHF2RdidwPHBTgf0Pj4j5paCROhv4YUS8APhh+rot2tFDqWijemm7VvTqMjNrWeCIiJuARyvS7oqIRu5abwS+lj7/GrCwgWM1pB09lIoGpdJ2rejVZWbWqb2qArhe0ipJZ5Sl7xkRD6XPfw/smXcASWdIWilp5aZNm5qewXb0UMoKVlme/PNWlq3u97gNM2uJTm0cf3lE9Et6NrBC0rq0BDMsIkJS5OxPRFwMXAzQ19eXu10jxruHUlZj++EvnMW1tz80Yk2NgcEhzrniDk44qJfLV/V7OVcza6qODBwR0Z/+3CjpSuBgknaRhyXtFREPSdoL2NjOfLZDVrC6cd2mUYsxDQ5t48Z1m/j48fu7V5WZNVXHBQ5JuwDTIuLx9PmRwL+kb18FnApckP78bqvyMdZurO3o/lqtLcPjNsys2VrWxiHpMuBnwDxJD0o6XdJxkh4E/hK4VtLydNvZkq5Ld90T+Kmk24BfANdGxPfT9y4AXiPpN8Bfp6+brtSNtX9gkODpbqy1pi8f636NcluGmY0nRbSk+r+j9PX1xcqVmUNGMh12wQ30Z3yL7+3p5uazj2j6fo3KGhjY3TV9RGO9BwKaWb0kraoYEgF0YFVVJyjajbXyZpwVNKodr1lqjVD3QEAzayYHjgx5QaC86ifrZiySfsTV9muVam0ZjazhYWZWyYEjQ5HJCbNuxgGjgkc7ur92SknIzCYnB44MRSYnzLvpBkmbRrvaEjqtJGRmk48DR45a3Vjzvsm3uiG8lk4uCZnZ5NCpU450vE5dTa9WScgLOJlZo1ziGKNmr7XRLJ1aEjKzycOBowGdOCq7VasOmpmVOHBMMp1aEjKzycOBYxLqxJKQmU0eDhwdyNODmFknc+AYo1bd3D09iJl1OgeOMWjlzb3o9CAulZhZu3gcxxhUu7k3qsgEi+2avt3MDBw4xqTo7LljUWRtjVYGLjOzWhw4xqCVCycVGZHeysBlZlaLA8cYtHK6kYULevn48ftXnR7EK/6ZWTu5cbygysboEw7q5cZ1m1rSOF1rHIZHh5tZO7UscEi6BDgW2BgR+6VpJwKLgRcBB0fEqPVcJe0NfJ1k7fEALo6Iz6XvLQbeBWxKN/9QRFxXeYxmy+pFdfmq/rZNFOjR4WbWTq0scXwVuIgkCJTcCRwPfLHKfluB90fErZJ2A1ZJWhERv0rfvzAiPtWKDOfpxBX0PDrczNqlZYEjIm6SNLci7S4ASdX2ewh4KH3+uKS7gF7gV7k7tZgbo83MntbRjeNp4FkA/Lws+UxJt0u6RNLM8ciHG6PNzJ7WsYFD0q7A5cBZEfFYmvyfwPOA+SSlkk9X2f8MSSslrdy0aVPeZoV06qJNZmbt0JGBQ1IXSdC4NCKuKKVHxMMRsS0itgNfAg7OO0ZEXBwRfRHRN2vWrIbyU6SLrJnZVNFx3XGVNIB8BbgrIj5T8d5eaRsIwHEkje3jwo3RZmaJlpU4JF0G/AyYJ+lBSadLOk7Sg8BfAtdKWp5uO1tSqVvtYcDbgCMkrUkfx6TvfVLSHZJuBw4H3tuq/JuZWTZFRLvz0HJ9fX2xcuWoISNmZlaFpFUR0VeZ3pFtHGZm1rkcOMzMrC4OHGZmVpcp0cYhaRNwf7vzUac9gEfanYkO4usxkq/HSL4eIzXreuwTEaPGM0yJwDERSVqZ1Sg1Vfl6jOTrMZKvx0itvh6uqjIzs7o4cJiZWV0cODrXxe3OQIfx9RjJ12MkX4+RWno93MZhZmZ1cYnDzMzq4sBhZmZ1ceAYZ+kCVBsl3VmWdqKktZK2S8rtQifpvnSSxzWSJsXkWznXY4mkdemCXVdK6snZ92hJ6yXdLenscct0CzV4PabK38dH02uxRtL1kmbn7HuqpN+kj1PHL9et0+D12FY2cexVDWUkIvwYxwfwCuBA4M6ytBcB84AfAX1V9r0P2KPdn2EcrseRwIz0+SeAT2TsNx24B3gusANwG/Didn+edl2PKfb38Yyy5/8b+ELGfrsD96Y/Z6bPZ7b787TreqTvPdGsfLjEMc4i4ibg0Yq0uyJifZuy1FY51+P6iNiavrwFeE7GrgcDd0fEvRHxFPBN4I0tzew4aOB6TEo51+Oxspe7AFk9fI4CVkTEoxGxGVgBHN2yjI6TBq5HUzlwTCwBXC9plaQz2p2ZcfJO4HsZ6b3AA2WvH0zTJru86wFT6O9D0r9KegA4BfhIxiZT6u+jwPUA2CldTvsWSQsbOZ8Dx8Ty8og4EHgt8PeSXtHuDLWSpHOBrcCl7c5LJyhwPabM30dEnBsRe5NcizPbnZ92K3g99olkGpK/AT4r6XljPZ8DxwQSEf3pz43AlVRZc32ik3QacCxwSqQVtBX6gb3LXj8nTZuUClyPKfX3UeZS4ISM9Cn191Em73qU/33cS9KeumCsJ3HgmCAk7SJpt9JzkgbTcVtzfTxJOhr4APCGiNiSs9kvgRdI2lfSDsBbgMZ6inSoItdjiv19vKDs5RuBdRmbLQeOlDRT0kyS67F8PPI33opcj/Q67Jg+34Nkie5fjfmk7e4lMNUewGXAQ8AQSb3r6cBx6fM/Aw8Dy9NtZwPXpc+fS9Jz6DZgLXBuuz9LC6/H3ST102vSxxcqr0f6+hjg1yS9q6b09Zhifx+XkwTF24Grgd502z7gy2X7vjO9dncD72j3Z2nn9QBeBtyR/n3cAZzeSD485YiZmdXFVVVmZlYXBw4zM6uLA4eZmdXFgcPMzOriwGFmZnVx4LBJS9KzymYD/b2k/rLXOzTpHD8qn9FY0tzymUvHi6TTJG1KP9uvJL0rZ7s3TJaZhK19ZrQ7A2atEhF/AOYDSFpMMjvop0rvS5oRT08eOBksjYgzJT0bWCvpqoh4uPRm+nmvYpIOlLTx4xKHTSmSvirpC5J+DnxS0mJJ/1T2/p2S5qbP3yrpF+m3+C9Kml7nuXaS9F/pGhmrJR2epp8m6aKy7a6R9CpJ09P83Znu8970/edJ+n46eeFPJL2w2nkjmXLkHmCfjM87fG5JeypZ3+O29PGyZnxum/xc4rCp6DnAyyJiW1oSGUXSi4CTgMMiYkjSf5DMPPr1jM0vlTSYPt8B2J4+/3sgImL/9GZ/vaS/qJKv+SSjfvdL89CTpl8MvCcifiPpEOA/gCPyDiLpuSQjye/O+LynlW3678CPI+K4NDjsWufntinKgcOmom9HxLYa27waOAj4pSSAbmBjzranRMRKSNo4gGvS9JcDnweIiHWS7geqBY57gedK+jxwLUmg2ZVkuohvp/kA2DFn/5MkvZxk6pp3R8Sj6T55n/cI4O1p/rYBf5T0tjo+t01RDhw2FT1Z9nwrI6tsd0p/CvhaRJzTgvNnnjMiNks6gGQRovcAbwbOAgYiYn6B4y6NiKwptZ/MSMvTys9tk4TbOGyqu49kKU4kHQjsm6b/EHhT2tCMpN0l7VPnsX9CUs1DWkU1B1ifnnO+pGmS9iad/jydtXRaRFwOfBg4MJLV3X4r6cR0G6XBpRl+CPyv9LjTJT2T5nxum+QcOGyquxzYXdJakgVwfg0QEb8iuXlfL+l2kqVH96rz2P8BTJN0B7AUOC0i/gzcDPyWZFrrfwduTbfvBX4kaQ3wDaD0rf8U4HRJpZlvm7VE7j8Ch6f5W0WyZnszPrdNcp4d18zM6uISh5mZ1cWBw8zM6uLAYWZmdXHgMDOzujhwmJlZXRw4zMysLg4cZmZWl/8PNMAD82rxKO0AAAAASUVORK5CYII=\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# let's evaluate our predictions respect to the real sale price\n",
    "plt.scatter(y_test, price_pipe.predict(X_test))\n",
    "plt.xlabel('True House Price')\n",
    "plt.ylabel('Predicted House Price')\n",
    "plt.title('Evaluation of Lasso Predictions')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# let's evaluate the distribution of the errors: \n",
    "# they should be fairly normally distributed\n",
    "\n",
    "y_test.reset_index(drop=True, inplace=True)\n",
    "\n",
    "preds = pd.Series(price_pipe.predict(X_test))\n",
    "\n",
    "errors = y_test - preds\n",
    "errors.hist(bins=30)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['price_pipe.joblib']"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# now let's save the scaler\n",
    "\n",
    "joblib.dump(price_pipe, 'price_pipe.joblib') "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Score new data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(1459, 37)\n"
     ]
    }
   ],
   "source": [
    "# load the unseen / new dataset\n",
    "data = pd.read_csv('test.csv')\n",
    "\n",
    "data.drop('Id', axis=1, inplace=True)\n",
    "\n",
    "data['MSSubClass'] = data['MSSubClass'].astype('O')\n",
    "\n",
    "data = data[FEATURES]\n",
    "\n",
    "print(data.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['MSZoning',\n",
       " 'Exterior1st',\n",
       " 'BsmtFullBath',\n",
       " 'KitchenQual',\n",
       " 'Functional',\n",
       " 'GarageCars',\n",
       " 'GarageArea']"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "new_vars_with_na = [\n",
    "    var for var in FEATURES\n",
    "    if var not in CATEGORICAL_VARS_WITH_NA_FREQUENT +\n",
    "    CATEGORICAL_VARS_WITH_NA_MISSING +\n",
    "    NUMERICAL_VARS_WITH_NA\n",
    "    and data[var].isnull().sum() > 0]\n",
    "\n",
    "new_vars_with_na"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>MSZoning</th>\n",
       "      <th>Exterior1st</th>\n",
       "      <th>BsmtFullBath</th>\n",
       "      <th>KitchenQual</th>\n",
       "      <th>Functional</th>\n",
       "      <th>GarageCars</th>\n",
       "      <th>GarageArea</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>RH</td>\n",
       "      <td>VinylSd</td>\n",
       "      <td>0.0</td>\n",
       "      <td>TA</td>\n",
       "      <td>Typ</td>\n",
       "      <td>1.0</td>\n",
       "      <td>730.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>RL</td>\n",
       "      <td>Wd Sdng</td>\n",
       "      <td>0.0</td>\n",
       "      <td>Gd</td>\n",
       "      <td>Typ</td>\n",
       "      <td>1.0</td>\n",
       "      <td>312.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>RL</td>\n",
       "      <td>VinylSd</td>\n",
       "      <td>0.0</td>\n",
       "      <td>TA</td>\n",
       "      <td>Typ</td>\n",
       "      <td>2.0</td>\n",
       "      <td>482.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>RL</td>\n",
       "      <td>VinylSd</td>\n",
       "      <td>0.0</td>\n",
       "      <td>Gd</td>\n",
       "      <td>Typ</td>\n",
       "      <td>2.0</td>\n",
       "      <td>470.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>RL</td>\n",
       "      <td>HdBoard</td>\n",
       "      <td>0.0</td>\n",
       "      <td>Gd</td>\n",
       "      <td>Typ</td>\n",
       "      <td>2.0</td>\n",
       "      <td>506.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "  MSZoning Exterior1st  BsmtFullBath KitchenQual Functional  GarageCars  \\\n",
       "0       RH     VinylSd           0.0          TA        Typ         1.0   \n",
       "1       RL     Wd Sdng           0.0          Gd        Typ         1.0   \n",
       "2       RL     VinylSd           0.0          TA        Typ         2.0   \n",
       "3       RL     VinylSd           0.0          Gd        Typ         2.0   \n",
       "4       RL     HdBoard           0.0          Gd        Typ         2.0   \n",
       "\n",
       "   GarageArea  \n",
       "0       730.0  \n",
       "1       312.0  \n",
       "2       482.0  \n",
       "3       470.0  \n",
       "4       506.0  "
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data[new_vars_with_na].head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "MSZoning        0.002742\n",
       "Exterior1st     0.000685\n",
       "BsmtFullBath    0.001371\n",
       "KitchenQual     0.000685\n",
       "Functional      0.001371\n",
       "GarageCars      0.000685\n",
       "GarageArea      0.000685\n",
       "dtype: float64"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data[new_vars_with_na].isnull().mean()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(1449, 37)\n"
     ]
    }
   ],
   "source": [
    "data.dropna(subset=new_vars_with_na, inplace=True)\n",
    "\n",
    "print(data.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "new_preds = price_pipe.predict(data)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<AxesSubplot:>"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# let's plot the predicted sale prices\n",
    "pd.Series(np.exp(new_preds)).hist(bins=50)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "# Conclusion\n",
    "\n",
    "Now we are ready for deployment!!!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.5"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {
    "height": "583px",
    "left": "0px",
    "right": "1324px",
    "top": "107px",
    "width": "212px"
   },
   "toc_section_display": "block",
   "toc_window_display": true
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
